package mpbft

import (
	"blockchain/public/entity"
	"blockchain/public/function"
	"bytes"
	"crypto/sha256"
	"encoding/json"
	"fmt"
)

type commit2Message struct {
	block entity.Block
	commit1Set [N/3+1] commit1Message
	sign string
	priSeq int
}

func commit2(priSeq int){
	var h [32]byte
	/**/
	hash,commit1Set:=getCommit1Message(priSeq)
	if hash!=h{
		var commit2 commit2Message
		commit2.block.Height=currentRound
		var prehash []byte
		if currentRound!=0{
			prehash,_=json.Marshal(blockchain[currentRound-1])
		}
		commit2.block.PreBlockHash=sha256.Sum256(prehash)
		commit2.block.Timestamp=TradeSet[priSeq][0].Timestamp
		commit2.block.Trades=TradeSet[priSeq]
		commit2.priSeq=priSeq
		commit2.commit1Set=commit1Set
		var data =make([][]byte,2)
		data[0],_=json.Marshal(commit2.block)
		data[1],_=json.Marshal(commit2.commit1Set)
		data1:=bytes.Join(data,[]byte(""))
		commit2.sign=function.Sign(data1,priSeq)
		var flagCommitted2 =make(chan bool)
		go sendCommit2ToNode(priSeq,flagCommitted2,&commit2)
		<-flagCommitted2

	}else{
		fmt.Printf("commit2:主节点%d出错\n",priSeq)
	}
}

func sendCommit2ToNode(priSeq int,flageCommittd2 chan bool,commit2 *commit2Message){
	for i:=0;i<N;i++{
		select {
		case chanNodeRecCommit2[i]<-*commit2:
			FlagCommitted2[priSeq][i]<-true
			close(FlagCommitted2[priSeq][i])
		default:
			FlagCommitted2[priSeq][i]<-false
			close(FlagCommitted2[priSeq][i])
		}
	}
	chanReply<-*commit2
	FlagReplied[priSeq]<-true
	close(FlagReplied[priSeq])
	flageCommittd2<-true
	close(flageCommittd2)
}

func getCommit1Message(priSeq int)([32]byte,[N/3+1]commit1Message){
	var commit1Verified [2*N/3+1] commit1Message
	var countSame[2*N/3+1] int
	var counter[2*N/3+1] int
	var consistentHash [32]byte
	var commit1Set[N/3+1] commit1Message
	for i:=0;i<2*N/3+1;i++{
		countSame[i]=N
	}
	count:=0
	for commit1 :=range chanPriRecCommit1[priSeq]{
		res:=function.VerifySignHash(commit1.tradeHash,commit1.sign,commit1.nodeSeq)
		if res{
			commit1Verified[count]=commit1
			count++
		}
	}

	for i:=0;i<2*N/3+1;i++{
		if countSame[i]==N{
			counter[i]=1
			countSame[i]=i
			for j:=i+1;j<2*N/3+1;j++{
				if commit1Verified[j].tradeHash==commit1Verified[i].tradeHash{
					countSame[j]=i
					counter[i]++
				}
			}
		}
	}
	for i:=0;i<2*N/3+1;i++{
		if counter[i]>N/3+1{
			consistentHash=commit1Verified[i].tradeHash
		}
	}
	count=0
	for i:=0;i<2*N/3+1;i++{
		if count==N/3+1{
			break;
		}else {
			if commit1Verified[i].tradeHash==consistentHash{
				commit1Set[count]=commit1Verified[count]
				count++
			}else {
				fmt.Printf("commit2:节点%d是拜占庭节点\n",commit1Verified[i].nodeSeq)
			}
		}
	}
	return consistentHash,commit1Set
}
